import { Injectable, OnModuleInit } from "@nestjs/common";
import axios from "axios";
import { FSWatcher, watch } from "chokidar";
import * as path from "node:path";
import { configuration, PACS_SETTING } from "../../../../config/config";
import { WithGatewayService } from "../micro/with-gateway/with-gateway.service";

const { username, password } = configuration.pacsServer;
const { instanceUrl, seriesUrl, studyUrl } = PACS_SETTING;
const chokidar = require("chokidar");
const fs = require("fs");

interface reqType {
  scanId: number | string;
  scoutId: any;
  watchFilePath: string;
  totalImgCount: number;
  scanType: string;
}

@Injectable()
export class WatchFileService implements OnModuleInit {
  watchers: FSWatcher[] = [];
  helperMap = new Map();
  fileCountMap = new Map();
  scanIdMap = new Map();

  constructor(private readonly socketIoGateway: WithGatewayService) {}

  async onModuleInit(): Promise<any> {
    console.log("启动监听程序，等待监听的文件路径1");
  }

  convert2Map(watchPathArr: reqType[]) {
    watchPathArr.map((eachParams) => {
      const filePath = path.normalize(eachParams.watchFilePath);
      console.log("normalize filePath:", filePath);
      this.helperMap.set(filePath, {
        scanId: eachParams.scanId,
        scanType: eachParams.scanType,
        scoutId: eachParams.scoutId || "",
        totalImgCount: eachParams.totalImgCount,
      });
      console.log(`this.helperMap set value finish`);
      this.fileCountMap.set(filePath, 0);
      if (this.scanIdMap.has(eachParams.scanId) && eachParams.scoutId) {
        const scoutIds = this.scanIdMap.get(eachParams.scanId);
        scoutIds.push(eachParams.scoutId);
      } else if (!this.scanIdMap.has(eachParams.scanId) && eachParams.scoutId) {
        this.scanIdMap.set(eachParams.scanId, []);
      }
    });
    console.log(
      `map 信息为: ${JSON.stringify(Array.from(this.helperMap.entries()))}`,
    );
  }

  async addNewListen(watchParamsArr: reqType[]): Promise<any> {
    this.convert2Map(watchParamsArr);
    if (this.watchers.length > 0) {
      try {
        this.watchers.map(async (watcher) => {
          await watcher.close();
        });
        this.watchers = [];
      } catch (err) {
        console.log(err);
      }
    }
    console.log("映射生成对于文件夹的监听11");
    watchParamsArr.map(async (watchParams) => {
      setTimeout(() => {
        const watchPath = path.resolve(watchParams.watchFilePath);
        console.log(`监听地址：${watchPath}的变化`);
        const watcher = chokidar.watch(watchPath, {
          persistent: false,
          ignoreInitial: true,
          usePolling: true, // 强制使用轮询
          interval: 500, // 轮询间隔
        });
        watcher.on("change", async (filePath) => {
          console.log("change", filePath);
        });

        watcher.on("add", async (eventPath) => {
          console.log(
            "监测到地址：",
            eventPath,
            ",发生变化：",
            "add",
            new Date().toISOString(),
          );
          const parentPath = path.normalize(watchParams.watchFilePath);
          const { scanId, totalImgCount, scoutId } =
            this.helperMap.get(parentPath);
          const fileCount = this.fileCountMap.get(parentPath);
          this.fileCountMap.set(parentPath, fileCount + 1);
          let finishFlag = false;
          if (fileCount + 1 === totalImgCount) {
            finishFlag = this.checkRelateScanFinished(scanId);
          }
          setTimeout(async () => {
            const { ParentStudy, ParentSeries } = await this.upload(eventPath);
            const uids = await this.getStudyAndSeriesUID({
              ParentStudy,
              ParentSeries,
            });
            const msg = {
              scanId: scanId,
              scoutId: scoutId,
              imageIds: uids,
              totalImgCount,
              currentCount: fileCount + 1,
              currentScanIdFinish: finishFlag,
            };
            console.log(`向前端发出消息:${JSON.stringify(msg)}`);
            this.socketIoGateway.sendMsg(msg);
          }, 1000);
        });
        this.watchers.push(watcher);
      }, 2000);
    });
  }

  checkRelateScanFinished(scanId) {
    const scoutIds = this.scanIdMap.get(scanId);
    return scoutIds.every((scoutId) => {
      const imgCounts = this.fileCountMap.get(scoutId);
      return imgCounts.currentCount + 1 === imgCounts.totalImgCount;
    });
  }

  private async upload(path1) {
    try {
      const dicomData = fs.readFileSync(path1);
      const res = await axios({
        method: "post",
        url: instanceUrl,
        data: dicomData,
        auth: {
          username: username,
          password: password,
        },
        headers: {
          "Content-Type": "application/dicom",
        },
      });
      console.log(new Date().toISOString(), "上传成功");
      const { ParentStudy, ParentSeries } = res.data;
      return { ParentStudy, ParentSeries };
    } catch (e) {
      console.error("DICOM文件上传失败:", e);
    }
  }

  private async getStudyAndSeriesUID({ ParentStudy, ParentSeries }) {
    const res = await axios({
      method: "get",
      url: studyUrl + `/${ParentStudy}`,
      auth: {
        username: username,
        password: password,
      },
    });
    const res1 = await axios({
      method: "get",
      url: seriesUrl + `/${ParentSeries}`,
      auth: {
        username: username,
        password: password,
      },
    });

    const studyUID = res.data.MainDicomTags.StudyInstanceUID;
    const seriesUID = res1.data.MainDicomTags.SeriesInstanceUID;
    return {
      studyUID,
      seriesUID,
    };
  }
}
